﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using System.Drawing.Drawing2D;

namespace Walson.Windows.Forms
{
    public partial class LedSegmentDisplay : Control
    {
        /// <summary>
        /// Led中的段（一个基本笔画），七段之一
        /// </summary>
        private class Segment
        {
            public Segment()
            {
                this.P = new Point[6];
            }
            /// <summary>
            /// 点数组
            /// </summary>
            public Point[] P;

            public Point DotCenter;
            public int DotRadiaus;
        }





        //         private int _Digit = 1;
        //         public int Digit
        //         {
        //             get
        //             {
        //                 return _Digit;
        //             }
        //             set
        //             {
        //                 _Digit = value;
        //                 this.Invalidate();
        //             }
        //         }

        private string _Value = "0";
        /// <summary>
        /// 数码管显示的值
        /// </summary>
        public char Value
        {
            get
            {
                return _Value.ToCharArray()[0];
            }
            set
            {
                string v = value.ToString().ToUpper();
                if(_Value!=v && CodeTable.ContainsKey(v))
                {
                    _Value = v;
                    this.Invalidate();
                }
            }
        }

        private Color _DarkColor = Color.DarkGreen;
        public Color DarkColor
        {
            get
            {
                return _DarkColor;
            }
            set
            {
                _DarkColor = value;
                _DarkBrush = new SolidBrush(value);
                this.Invalidate();
            }
        }

        private Color _LightColor = Color.Lime;
        public Color LightColor
        {
            get
            {
                return _LightColor;
            }
            set
            {
                _LightColor = value;
                _LightBrush = new SolidBrush(value);
                this.Invalidate();
            }
        }

        /// <summary>
        /// 笔画宽度
        /// </summary>
        private int m_SectionThick = 11;
        public int SegmentWidth
        {
            get
            {
                return m_SectionThick;
            }
            set
            {
                m_SectionThick = value;
                this.ComputeSections(this.Width, this.Height);
                this.Invalidate();
            }
        }

        private bool _Dotted = false;
        public bool Dotted
        {
            get
            {
                return _Dotted;
            }
            set
            {
                _Dotted = value;
                this.Invalidate();
            }
        }

        private bool _Colon=false;
        public bool Colon
        {
            get
            {
                return _Colon;
            }
            set
            {
                if(_Colon)
                {
                    _Dotted = false;
                    _DotVisiable = false;
                }

                _Colon = value;
                this.Invalidate();
            }
        }

        private bool _DotVisiable = true;
        public bool DotVisiable
        {
            get
            {
                return _DotVisiable;
            }
            set
            {
                _DotVisiable = value;
                this.Invalidate();
            }
        }

        private bool _On = true;
        /// <summary>
        /// 数码管是否开启
        /// </summary>
        public bool On
        {
            get
            {
                return _On;
            }
            set
            {
                if(_On!=value)
                {
                    _On = value;
                    this.Invalidate();
                }
            }
        }

        //public delegate void onUpperPartClicked();


        private Segment[] m_Sections = new Segment[8];

        private SolidBrush _DarkBrush;
        private SolidBrush _LightBrush;

        private Dictionary<string, byte[]> CodeTable = new Dictionary<string, byte[]>();

//         private byte[][] OldCodeTable =
//             {
//             new byte[]{ 1,0,1,1,1,1,1}, // 0
//             new byte[]{ 0,0,0,0,1,0,1}, // 1
//             new byte[]{ 1,1,1,0,1,1,0}, // 2
//             new byte[]{1,1,1,0,1,0,1 }, // 3
//             new byte[]{ 0,1,0,1,1,0,1}, // 4
//             new byte[]{ 1,1,1,1,0,0,1}, // 5
//             new byte[]{ 1,1,1,1,0,1,1}, // 6
//             new byte[]{ 0,0,1,1,1,0,1}, // 7
//             new byte[]{ 1,1,1,1,1,1,1}, // 8
//             new byte[]{ 1,1,1,1,1,0,1}, // 9
//             new byte[]{ 0,1,1,1,1,1,1}, // A
//             new byte[]{ 1,1,0,1,0,1,1}, // B
//             new byte[]{ 1,0,1,1,0,1,0}, // C
//             new byte[]{ 1,1,0,0,1,1,1}, // D
//             new byte[]{ 1,1,1,1,0,1,0}, // E
//             new byte[]{ 0,1,1,1,0,1,0}, // F
//             new byte[]{ 0,1,0,0,0,0,0}  // -
//             };

        /*
         
             __     2
          3 |  |    4
             --     1
          5 |  |    6
             --     0
             
             
             */



        private void InitCodeTable()
        {
            CodeTable.Add("0", new byte[] { 1, 0, 1, 1, 1, 1, 1 });
            CodeTable.Add("1", new byte[] { 0, 0, 0, 0, 1, 0, 1 });
            CodeTable.Add("2", new byte[] { 1, 1, 1, 0, 1, 1, 0 });
            CodeTable.Add("3", new byte[] { 1, 1, 1, 0, 1, 0, 1 });
            CodeTable.Add("4", new byte[] { 0, 1, 0, 1, 1, 0, 1 });
            CodeTable.Add("5", new byte[] { 1, 1, 1, 1, 0, 0, 1 });
            CodeTable.Add("6", new byte[] { 1, 1, 1, 1, 0, 1, 1 });
            CodeTable.Add("7", new byte[] { 0, 0, 1, 1, 1, 0, 1 });
            CodeTable.Add("8", new byte[] { 1, 1, 1, 1, 1, 1, 1 });
            CodeTable.Add("9", new byte[] { 1, 1, 1, 1, 1, 0, 1 });
            CodeTable.Add("A", new byte[] { 0, 1, 1, 1, 1, 1, 1 });
            CodeTable.Add("B", new byte[] { 1, 1, 0, 1, 0, 1, 1 });
            CodeTable.Add("C", new byte[] { 1, 0, 1, 1, 0, 1, 0 });
            CodeTable.Add("D", new byte[] { 1, 1, 0, 0, 1, 1, 1 });
            CodeTable.Add("E", new byte[] { 1, 1, 1, 1, 0, 1, 0 });
            CodeTable.Add("F", new byte[] { 0, 1, 1, 1, 0, 1, 0 });
            CodeTable.Add("G", new byte[] { 1, 1, 1, 1, 1, 0, 1 });
            CodeTable.Add("H", new byte[] { 0, 1, 0, 1, 1, 1, 1 });
            CodeTable.Add("L", new byte[] { 1, 0, 0, 1, 0, 1, 0 });
            CodeTable.Add("N", new byte[] { 0, 0, 1, 1, 1, 1, 1 });
            CodeTable.Add("O", new byte[] { 1, 0, 1, 1, 1, 1, 1 });
            CodeTable.Add("P", new byte[] { 0, 1, 1, 1, 1, 1, 0 });
            CodeTable.Add("Q", new byte[] { 0, 1, 1, 1, 1, 0, 1 });
            CodeTable.Add("R", new byte[] { 0, 1, 0, 1, 0, 1, 0 });
            CodeTable.Add("S", new byte[] { 1, 1, 1, 1, 0, 0, 1 });
            CodeTable.Add("T", new byte[] { 1, 1, 0, 1, 0, 1, 0 });
            CodeTable.Add("U", new byte[] { 1, 0, 0, 1, 1, 1, 1 });
            CodeTable.Add("Y", new byte[] { 1, 1, 0, 1, 1, 0, 1 });
            CodeTable.Add("-", new byte[] { 0, 1, 0, 0, 0, 0, 0 });
            CodeTable.Add(" ", new byte[] { 0, 0, 0, 0, 0, 0, 0 });
        }


        /// <summary>
        /// 重新计算段的坐标！！！（这种方法得出的图形将是矢量的，不受缩放影响）
        /// </summary>
        private void ComputeSections(int ledwidth, int ledheight)
        {
            //计算出控件中心点的坐标
            int cx = ledwidth / 2;
            int cy = ledheight / 2;

            int t1 = this.m_SectionThick * 3 / 4;   //大斜坡长
            int t2 = this.m_SectionThick / 4;   //小斜坡长
            int t3 = this.m_SectionThick / 2;   //中斜坡长段的一半长度！

            int hw = cx - this.m_SectionThick - this.m_SectionThick; ;  //half width of section 距离边缘5像素
            int hh = cy - this.m_SectionThick - 4;   //half height of section
            Segment[] s = this.m_Sections;


            //第0段（最底下一横）
            s[0].P[0].X = cx - hw - this.m_SectionThick * 5 / 16;
            s[0].P[0].Y = cy + hh + this.m_SectionThick * 3 / 16;
            s[0].P[1].X = s[0].P[0].X - t2;
            s[0].P[1].Y = s[0].P[0].Y - t2;
            s[0].P[2].X = s[0].P[1].X + t1;
            s[0].P[2].Y = s[0].P[1].Y - t1;

            

            //第1段(它是中间的一横，因为和其他任何段都没对称关系，只能手写！)
            s[1].P[0].X = cx - hw + this.m_SectionThick * 5 / 16;
            s[1].P[0].Y = cy + t3;
            s[1].P[1].X = s[1].P[0].X - t3;
            s[1].P[1].Y = s[1].P[0].Y - t3;
            s[1].P[2].X = s[1].P[0].X;
            s[1].P[2].Y = cy - t3;

            //第2段(最上面一横，与第0段按y轴对称)
            for (int i = 0; i < 3; i++)
            {
                s[2].P[i].X = s[0].P[2 - i].X;
                s[2].P[i].Y = ledheight - s[0].P[2 - i].Y;
            }
            //循环为0，1，2三个水平段的p[3],p[4],p[5]赋值，注意这几个值可以根据钱三个点求出
            for (int i = 0; i < 3; i++)
            {
                for (int j = 3; j < 6; j++)
                {
                    s[i].P[j].X = ledwidth - s[i].P[5 - j].X;
                    s[i].P[j].Y = s[i].P[5 - j].Y;
                }
            }
            //到这里我们已经计算好了0，1，2段的全部坐标，下面开始计算3~6段，他们具有相互对称的关系！

            //第3段（左上的竖）(注意本身自己也不具备对称关系，6个点都要手写)
            s[3].P[0].X = cx - hw + this.m_SectionThick / 5;
            s[3].P[0].Y = cy - this.m_SectionThick * 3 / 5;
            s[3].P[1].X = s[3].P[0].X - t3;
            s[3].P[1].Y = s[3].P[0].Y + t3;
            s[3].P[2].X = s[3].P[1].X - t3;
            s[3].P[2].Y = s[3].P[1].Y - t3;
            s[3].P[3].X = s[3].P[2].X;
            s[3].P[3].Y = s[3].P[0].Y - hh + this.m_SectionThick;
            s[3].P[4].X = s[3].P[3].X + t2;
            s[3].P[4].Y = s[3].P[3].Y - t2;
            s[3].P[5].X = s[3].P[4].X + t1;
            s[3].P[5].Y = s[3].P[4].Y + t1;

            //计算4,5,6段的点坐标（4和3段x对称,5和3是y对称,6和3是原点对称）
            for (int i = 0; i < 6; i++)
            {
                int m = (8 - i) % 6;
                s[4].P[i].X = ledwidth - s[3].P[m].X;
                s[4].P[i].Y = s[3].P[m].Y;

                s[5].P[i].X = s[3].P[m].X;
                s[5].P[i].Y = ledheight - s[3].P[m].Y;

                s[6].P[i].X = ledwidth - s[3].P[i].X;
                s[6].P[i].Y = ledheight - s[3].P[i].Y;
            }


            for (int i = 0; i < 7; i++)
            {
                for (int j = 0; j < 6; j++)
                {
                    s[i].P[j].X-= this.m_SectionThick;
                }
            }

            s[7].DotCenter.X = s[0].P[4].X + this.m_SectionThick / 2;
            s[7].DotCenter.Y = s[0].P[4].Y - this.m_SectionThick / 2;
            s[7].DotRadiaus = m_SectionThick;
        }

        private void LedSegmentDisplay_Resize(object sender, EventArgs e)
        {
            this.ComputeSections(this.Width, this.Height);
        }

        

        





        public LedSegmentDisplay()
        {
            this.LightColor = Color.Lime;
            this.DarkColor = Color.DarkGreen;

            for (int i = 0; i < m_Sections.Length; i++)
            {
                m_Sections[i] = new Segment();
            }

            InitCodeTable();

            InitializeComponent();

            this.SetStyle(ControlStyles.DoubleBuffer
                | ControlStyles.AllPaintingInWmPaint
                | ControlStyles.UserPaint
                | ControlStyles.ResizeRedraw,
                true);

            this.Resize += LedSegmentDisplay_Resize;
            this.MouseClick += LedSegmentDisplay_MouseClick;
        }

        

        public LedSegmentDisplay(IContainer container)
        {
            container.Add(this);

            this.LightColor = Color.Lime;
            this.DarkColor = Color.DarkGreen;

            for (int i = 0; i < m_Sections.Length; i++)
            {
                m_Sections[i] = new Segment();
            }
            InitCodeTable();
            InitializeComponent();
            this.SetStyle(ControlStyles.DoubleBuffer
                | ControlStyles.AllPaintingInWmPaint
                | ControlStyles.UserPaint
                | ControlStyles.ResizeRedraw,
                true);
            this.Resize += LedSegmentDisplay_Resize;
            this.MouseClick += LedSegmentDisplay_MouseClick;
        }

        private void LedSegmentDisplay_MouseClick(object sender, MouseEventArgs e)
        {
            if(e.X>this.Width/2)
            {

            }
        }

        private void LedSegmentDisplay_Click(object sender, EventArgs e)
        {
            
        }


        protected override void OnPaint(PaintEventArgs e)
        {
            using (Bitmap bmp = new Bitmap(this.Width, this.Height))
            {
                using (Graphics g = Graphics.FromImage(bmp))
                {
                    g.Clear(this.BackColor);
                    if(_On==false)
                    {
                        if (_Colon)
                        {
                            g.FillEllipse(_DarkBrush, m_Sections[1].DotCenter.X, this.Height*3 / 8, this.SegmentWidth, this.SegmentWidth);
                            g.FillEllipse(_DarkBrush, m_Sections[1].DotCenter.X, this.Height * 5 / 8, this.SegmentWidth, this.SegmentWidth);
                        }
                        else
                        {
                            for (int i = 0; i < m_Sections.Length - 1; i++)
                            {
                                g.FillPolygon(_DarkBrush, m_Sections[i].P);
                            }
                        }
                    }
                    else if (Value == -1)
                    {
                        for (int i = 0; i < m_Sections.Length - 1; i++)
                        {
                            if(CodeTable[_Value][i]==1)
                            {
                                g.FillPolygon(_LightBrush, m_Sections[i].P);
                            }
                            else
                            {
                                g.FillPolygon(_DarkBrush, m_Sections[i].P);
                            }
                        }
                    }
                    else if(_Colon)
                    {
                        g.FillEllipse(_LightBrush, m_Sections[1].DotCenter.X, this.Height*3 / 8, this.SegmentWidth, this.SegmentWidth);
                        g.FillEllipse(_LightBrush, m_Sections[1].DotCenter.X, this.Height * 5 / 8, this.SegmentWidth, this.SegmentWidth);
                    }
                    else
                    {
                        for (int i = 0; i < m_Sections.Length - 1; i++)
                        {
                            if (CodeTable[_Value][i] == 1)
                            {
                                g.FillPolygon(_LightBrush, m_Sections[i].P);
                            }
                            else
                            {
                                g.FillPolygon(_DarkBrush, m_Sections[i].P);
                            }
                        }

                        if (_DotVisiable)
                        {
                            if (_Dotted)
                            {
                                g.FillEllipse(_LightBrush, m_Sections[7].DotCenter.X, m_Sections[7].DotCenter.Y, m_Sections[7].DotRadiaus, m_Sections[7].DotRadiaus);
                            }
                            else
                            {
                                g.FillEllipse(_DarkBrush, m_Sections[7].DotCenter.X, m_Sections[7].DotCenter.Y, m_Sections[7].DotRadiaus, m_Sections[7].DotRadiaus);
                            }
                        }
                    }
                }
                e.Graphics.DrawImage(bmp, 0, 0);
            }

            base.OnPaint(e);
        }
    }
}
